package com.codeplex.jtfscli.util;

import java.io.File;
import java.text.ParseException;

import com.microsoft.tfs.core.clients.versioncontrol.soapextensions.RecursionType;
import com.microsoft.tfs.core.clients.versioncontrol.specs.ItemSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.LabelSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.WorkspaceSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.ChangesetVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.DateVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.LabelVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.LatestVersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.VersionSpec;
import com.microsoft.tfs.core.clients.versioncontrol.specs.version.WorkspaceVersionSpec;

/**
 * Constructs ItemSpecs and VersionSpecs.
 * 
 * This allows us to do testing more easily.
 * 
 * @author jack
 * 
 */
public class SpecFactory {
	/**
	 * Determines which VersionSpec to construct based on the first character of
	 * versionSpec, then constructs and returns that instance.
	 * 
	 * @param versionSpec
	 * @param workspace
	 *            If versionSpec is 'W' (or could be 'W'), workspace will be
	 *            used to generate the WorkspaceVersionSpec. This argument can
	 *            be null. However, if it is null and versionSpec.equals("W"),
	 *            this function will throw an IllegalArgumentException.
	 * @return
	 * @throws ParseException
	 *             If versionSpec is a malformed date.
	 */
	public VersionSpec createVersionSpec(final String versionSpec,
			final WorkspaceSpec workspace) throws ParseException {
		switch (versionSpec.charAt(0)) {
		case 'D':
			return new DateVersionSpec(versionSpec.substring(1));
		case 'C':
			return new ChangesetVersionSpec(Integer.parseInt(versionSpec
					.substring(1)));
		case 'L':
			return new LabelVersionSpec(new LabelSpec(versionSpec.substring(1),
					null));
		case 'T':
			return LatestVersionSpec.INSTANCE;
		case 'W':
			if (workspace == null)
				throw new IllegalArgumentException(
						"Workspace cannot be null if versionSpec.equals(\"W\").");
			return new WorkspaceVersionSpec(workspace);
		default:
			throw new IllegalArgumentException(
					"Could not determine the type of versionspec: ."
							+ versionSpec);
		}
	}

	/**
	 * Constructs and returns an ItemSpec that can be used with TFS.
	 * 
	 * @param localOrServerPath
	 *            A path to a local directory or server directory.
	 * @param isRecursive
	 *            True for a fully recursive itemspec.
	 * @return
	 */
	public ItemSpec createItemspec(final String localOrServerPath,
			final boolean isRecursive) {
		// TFS requires absolute paths for local directories.
		// Also, you cannot use a "." as a directory otherwise TFS will become
		// confused.
		final String itemSpecPath;
		if (Util.isServerPath(localOrServerPath))
			itemSpecPath = localOrServerPath;
		else
			itemSpecPath = new File(localOrServerPath.equals(".") ? ""
					: localOrServerPath).getAbsolutePath();
		return new ItemSpec(itemSpecPath, isRecursive ? RecursionType.FULL
				: RecursionType.NONE);
	}
}
